package com.pioneer.cloudstorage.controller;

import com.pioneer.cloudstorage.pojo.dto.ChangeFolderDTO;
import com.pioneer.cloudstorage.pojo.dto.CreateFolderDTO;
import com.pioneer.cloudstorage.pojo.dto.FileUploadDTO;
import com.pioneer.cloudstorage.pojo.entity.FileMetadata;
import com.pioneer.cloudstorage.pojo.entity.Result;
import com.pioneer.cloudstorage.pojo.vo.ResultUpload;
import com.pioneer.cloudstorage.service.FilesService;
import com.pioneer.cloudstorage.utils.BaseContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@Slf4j
@RequestMapping("/api/files")
public class Files {
    @Autowired
    private FilesService filesService;
    @GetMapping()
    public Result list(@RequestParam(defaultValue = "0" )Integer parentId) {
        log.info("获取当前目录文件列表");
        List<FileMetadata > file = filesService.list(parentId);
        return Result.success(file);
    }
    @PostMapping ("folder")
    public Result createFolder(@RequestBody CreateFolderDTO  createFolderDTO) {
        log.info("创建文件夹");
        return filesService.createFolder(createFolderDTO);
    }


     //文件上传，上传至根目录storage/userId/date/originalFileName
    /**
     * POST /api/files/upload
     * 支持两阶段上传：
     * 1. 第一阶段（秒传检查）：只传 fileMd5，不传 file
     * 2. 第二阶段（实际上传）：传 file 和 fileMd5
     */
    @PostMapping("/upload")
    public ResponseEntity<ResultUpload> uploadFile(
            @RequestParam(value = "file", required = false) MultipartFile file,
            @RequestParam(value = "fileName", required = false) String fileName,
            @RequestParam(value = "fileMd5", required = false)  String fileMd5,
            @RequestParam(value = "parentId", required = false, defaultValue = "0") Long parentId) {

        // 从JWT Token中获取用户ID
        Long userId = BaseContext.getCurrentId();

        FileUploadDTO fileUploadDTO = new FileUploadDTO();
        fileUploadDTO.setFile(file);
        fileUploadDTO.setParentId(parentId);
        fileUploadDTO.setFileMd5(fileMd5);
        fileUploadDTO.setFileName(fileName);


        ResultUpload fileMetadata = filesService.uploadFile(fileUploadDTO, userId);
        if (file != null) {
            log.info("用户 {} 上传文件成功: {}", userId, file.getOriginalFilename());
        }

        log.info(String.valueOf(fileMetadata));
        return ResponseEntity.ok(fileMetadata);

    }

    /**
     * 下载文件
     */
    @GetMapping("/download/{fileId}")
    public void downloadFile(@PathVariable Long fileId,
                             HttpServletResponse response,
                             HttpServletRequest request) {
        try {
            Long userId = BaseContext.getCurrentId();
            log.info("用户 {} 请求下载文件 {}", userId, fileId);

            filesService.downloadFile(fileId, userId, response);

        } catch (RuntimeException e) {
            log.error("文件下载业务异常 - 文件ID: {}", fileId, e);
            sendErrorResponse(response, e.getMessage());
        } catch (IOException e) {
            log.error("文件下载IO异常 - 文件ID: {}", fileId, e);
            sendErrorResponse(response, "文件下载失败");
        } catch (Exception e) {
            log.error("文件下载系统异常 - 文件ID: {}", fileId, e);
            sendErrorResponse(response, "系统错误");
        }
    }

    /**
     * 发送错误响应（JSON格式）
     */
    private void sendErrorResponse(HttpServletResponse response, String errorMessage) {
        try {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            response.setContentType("application/json;charset=UTF-8");

            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("code", 2);
            errorResult.put("msg", errorMessage);
            errorResult.put("data", null);

            String jsonResponse = new com.fasterxml.jackson.databind.ObjectMapper()
                    .writeValueAsString(errorResult);

            response.getWriter().write(jsonResponse);
            response.getWriter().flush();
        } catch (IOException ioException) {
            log.error("发送错误响应失败", ioException);
        }
    }

    /**
     * 文件预览（在线查看，不下载）
     */
    @GetMapping("/preview/{fileId}")
    public void previewFile(@PathVariable Long fileId,
                            HttpServletResponse response,
                            HttpServletRequest request) {
        try {
            Long userId = BaseContext.getCurrentId();
            log.info("用户 {} 请求预览文件 {}", userId, fileId);

            // 获取文件元数据
            FileMetadata fileMetadata = filesService.getFileMetadata(fileId, userId);

            // 设置预览头（inline）
            File physicalFile = getPhysicalFile(fileMetadata);
            if (physicalFile == null || !physicalFile.exists()) {
                throw new RuntimeException("文件不存在");
            }

            String fileName = fileMetadata.getFileName();
            String encodedFileName = java.net.URLEncoder.encode(fileName, "UTF-8")
                    .replaceAll("\\+", "%20");

            // 对于可预览的文件类型，使用 inline
            if (isPreviewableFile(fileMetadata.getMimeType())) {
                response.setHeader("Content-Disposition", "inline; filename=\"" + encodedFileName + "\"");
            } else {
                response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"");
            }

            response.setContentType(fileMetadata.getMimeType() != null ?
                    fileMetadata.getMimeType() : "application/octet-stream");
            response.setHeader("Content-Length", String.valueOf(physicalFile.length()));

            // 写入文件流
            try (java.io.InputStream inputStream = new java.io.FileInputStream(physicalFile)) {
                org.apache.tomcat.util.http.fileupload.IOUtils.copy(inputStream, response.getOutputStream());
                response.getOutputStream().flush();
            }

            log.info("文件预览成功 - 文件ID: {}, 用户ID: {}", fileId, userId);

        } catch (Exception e) {
            log.error("文件预览失败 - 文件ID: {}", fileId, e);
            sendErrorResponse(response, e.getMessage());
        }
    }

    /**
     * 检查文件类型是否支持预览
     */
    private boolean isPreviewableFile(String mimeType) {
        if (mimeType == null) return false;

        return mimeType.startsWith("image/") ||
                mimeType.startsWith("text/") ||
                mimeType.equals("application/pdf") ||
                mimeType.equals("application/msword") ||
                mimeType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
    }

    /**
     * 获取物理文件（复用Service中的逻辑）
     */
    private File getPhysicalFile(FileMetadata fileMetadata) {
        // 这里简化实现，实际应该调用Service中的方法
        String filePath = fileMetadata.getFilePath();

        // 尝试绝对路径
        File file = new File(filePath);
        if (file.exists()) return file;

        // 尝试相对路径
        file = new File(System.getProperty("user.dir"), filePath);
        if (file.exists()) return file;

        // 尝试storage目录
        file = new File("storage", filePath);
        if (file.exists()) return file;

        return null;
    }

    @PutMapping("/{fileId}")
    public Result updateFile(@PathVariable Long fileId,@RequestBody ChangeFolderDTO updateFileDTO) {
        Long userId = BaseContext.getCurrentId();
        log.info("用户 {} 更新文件 {}", userId, fileId);
        return filesService.updateFile(fileId, updateFileDTO, userId);
    }

    @DeleteMapping("/{fileId}")
    public Result deleteFile(@PathVariable Long fileId) {
        Long userId = BaseContext.getCurrentId();
        log.info("用户 {} 逻辑删除文件 {}", userId, fileId);
        return filesService.deleteFile(fileId, userId);
    }
}
